package cn.virens.support;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.server.ServerGroupContext;
import org.tio.server.TioServer;
import org.tio.utils.thread.pool.DefaultThreadFactory;
import org.tio.utils.thread.pool.SynThreadPoolExecutor;

import cn.virens.TCPServer;
import cn.virens.TioHandler;
import cn.virens.TioListener;
import cn.virens.app.main.Component;
import cn.virens.packet.handler.HeartbeatHandler;
import cn.virens.packet.handler.LoginHandler;
import cn.virens.packet.handler.ReplyHandler;
import cn.virens.packet.handler.ReportSensorHandler;

/**
 * TCP 服务管理器
 * 
 * @作者   : loioi
 * @创建时间 :2017年12月10日 上午11:42:24
 */
public class TCPServerImpl implements TCPServer, Component {
	protected final Logger logger = LoggerFactory.getLogger(TCPServerImpl.class);
	protected final TioServer mTioServer = new TioServer(null);

	private static final long KEEP_ALIVE_TIME = 90L;
	private static final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2;
	private static final int MAX_POOL_SIZE = CORE_POOL_SIZE * 4 < 128 ? 128 : CORE_POOL_SIZE * 4;

	private int port;

	private ThreadPoolExecutor groupExecutor;
	private SynThreadPoolExecutor tioExecutor;

	protected TioHandler serverTioHandler;
	protected TioListener serverTioListener;
	protected ServerGroupContext serverGroupContext;

	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}

	@Override
	public void initialize() throws Exception {
		logger.debug("The TCP Server initialize--------------------------");

		// TIO 执行队列
		LinkedBlockingQueue<Runnable> tioQueue = new LinkedBlockingQueue<>();
		DefaultThreadFactory threadFactory0 = DefaultThreadFactory.getInstance("tio-tcp", Thread.NORM_PRIORITY);
		this.tioExecutor = new SynThreadPoolExecutor(CORE_POOL_SIZE, CORE_POOL_SIZE, KEEP_ALIVE_TIME, tioQueue, threadFactory0, "tio-tcp");
		this.tioExecutor.prestartAllCoreThreads();

		// TIO 分组队列
		LinkedBlockingQueue<Runnable> groupQueue = new LinkedBlockingQueue<>();
		DefaultThreadFactory threadFactory1 = DefaultThreadFactory.getInstance("tio-tcp-group", Thread.NORM_PRIORITY);
		this.groupExecutor = new ThreadPoolExecutor(MAX_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, groupQueue, threadFactory1);
		this.groupExecutor.prestartAllCoreThreads();

		// 初始化TIO
		this.serverTioHandler = new TioHandler();
		this.serverTioListener = new TioListener();
		this.serverGroupContext = new ServerGroupContext(serverTioHandler, serverTioListener, tioExecutor, groupExecutor);
		this.serverGroupContext.setName("TCP ServerGroup");
		this.serverGroupContext.setHeartbeatTimeout(0);

		// 添加包处理事件
		this.serverTioHandler.addHandler("0000", new LoginHandler());
		this.serverTioHandler.addHandler("0001", new HeartbeatHandler());
		this.serverTioHandler.addHandler("0004", new ReportSensorHandler());//数据上报
		this.serverTioHandler.addHandler("8002", new ReportSensorHandler());//数据查询
		this.serverTioHandler.addHandler("8003", new ReplyHandler());

		// 启动TCP服务
		this.mTioServer.setServerGroupContext(serverGroupContext);
		this.mTioServer.start(null, port);
	}

	@Override
	public void destroy() throws Exception {
		logger.debug("The TCP Server stoping...");

		this.mTioServer.stop();
	}
}
